<template>
  <div>
    <el-drawer v-bind="$attrs" @opened="onOpen" @close="onClose">
      <div class="action-bar" :style="{ 'text-align': 'left' }">
        <span class="bar-btn" @click="refresh">
          <i class="el-icon-refresh"></i>
          刷新
        </span>
        <span ref="copyBtn" @click="copyCode" class="bar-btn copy-json-btn">
          <i class="el-icon-document-copy"></i>
          复制JSON
        </span>
        <span class="bar-btn" @click="exportJsonFile">
          <i class="el-icon-download"></i>
          导出JSON文件
        </span>
        <span
          class="bar-btn delete-btn"
          @click="$emit('update:visible', false)"
        >
          <i class="el-icon-circle-close"></i>
          关闭
        </span>
      </div>
      <div id="editorJson" class="json-editor"></div>
    </el-drawer>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, computed } from "vue";
import { beautifierConf } from "../utils/common";
import { useClipboard } from "@vueuse/core";
import { saveAs } from "file-saver";
import beautifier from "js-beautify";
import * as monaco from "monaco-editor";

const props = defineProps({
  jsonStr: {
    type: String,
    required: true,
  },
});

const jsonEditor = ref(null);
const beautifierJson = ref("");

const { copy, isSupported } = useClipboard({ source: beautifierJson });

const preventDefaultSave = (e) => {
  if (e.key === "s" && (e.metaKey || e.ctrlKey)) {
    e.preventDefault();
    copyCode();
  }
};

const copyCode = () => {
  if (!isSupported) {
    ElMessageBox.message({
      showClose: true,
      message: "浏览器不支持复制",
      type: "warning",
    });
    return;
  }
  copy(beautifierJson.value);
  ElMessageBox.message({
    showClose: true,
    message: "代码已复制到剪切板，可粘贴。",
    type: "success",
  });
};

const onOpen = () => {
  beautifierJson.value = beautifier.js(props.jsonStr, beautifierConf.js);
  setEditorValue("editorJson", beautifierJson.value);
};

const onClose = () => {};

const setEditorValue = (id, codeStr) => {
  if (jsonEditor.value) {
    jsonEditor.value.setValue(codeStr);
  } else {
    jsonEditor.value = monaco.value.editor.create(document.getElementById(id), {
      value: codeStr,
      theme: "vs-dark",
      language: "json",
      automaticLayout: true,
    });
    jsonEditor.value.onKeyDown((e) => {
      if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {
        refresh();
      }
    });
  }
};

const exportJsonFile = () => {
  $prompt("文件名:", "导出文件", {
    inputValue: `${+new Date()}.json`,
    closeOnClickModal: false,
    inputPlaceholder: "请输入文件名",
  }).then(({ value }) => {
    if (!value) value = `${+new Date()}.json`;
    const codeStr = jsonEditor.value.getValue();
    const blob = new Blob([codeStr], { type: "text/plain;charset=utf-8" });
    saveAs(blob, value);
  });
};

const refresh = () => {
  try {
    emit("refresh", JSON.parse(jsonEditor.value.getValue()));
  } catch (error) {
    $notify({
      title: "错误",
      message: "JSON格式错误，请检查",
      type: "error",
    });
  }
};

const emit = defineEmits(["refresh"]);

onMounted(() => {
  window.addEventListener("keydown", preventDefaultSave);
});

onBeforeUnmount(() => {
  window.removeEventListener("keydown", preventDefaultSave);
});
</script>

<style lang="scss" scoped>
@use "../mixin.scss" as *;

:deep(.el-drawer__header) {
  display: none;
}

@include action-bar;

.json-editor {
  height: calc(100vh - 33px);
}
</style>
